home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / oogl / refcomm / handle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-05  |  6.8 KB  |  304 lines

  1. /* Copyright (c) 1992 The Geometry Center; University of Minnesota
  2.    1300 South Second Street;  Minneapolis, MN  55454, USA;
  3.    
  4. This file is part of geomview/OOGL. geomview/OOGL is free software;
  5. you can redistribute it and/or modify it only under the terms given in
  6. the file COPYING, which you should have received along with this file.
  7. This and other related software may be obtained via anonymous ftp from
  8. geom.umn.edu; email: software@geom.umn.edu. */
  9.  
  10. /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
  11.  
  12. #include <string.h>
  13. #include "handleP.h"
  14.  
  15.  
  16. Handle *AllHandles = NULL;
  17.  
  18. void
  19. HandleUpdRef(Handle **hp, Ref *parent, Ref **objp)
  20. {
  21.     register Handle *h;
  22.  
  23.     if((h = *hp) != NULL && objp != NULL && h->object != *objp) {
  24.     if(h->ops->Delete) {
  25.         RefIncr((Ref *)h->object);
  26.         if(*objp) (*h->ops->Delete)(*objp);
  27.     }
  28.     *objp = h->object;
  29.     }
  30. }
  31.         
  32. void HandleUnregister(Handle **hp)
  33. {
  34.     register Handle *h;
  35.     register HRef *rp;
  36.     register int i;
  37.  
  38.     if(hp == NULL || (h = *hp) == NULL)
  39.     return;
  40.     for(i = h->nrefs, rp = &h->refs[i]; --i >= 0; ) {
  41.     rp--;
  42.     if(rp->hp == hp)
  43.         *rp = h->refs[--h->nrefs];
  44.     }
  45. }
  46.  
  47. void HandleUnregisterJust(Handle **hp, Ref *obj, void *info, void (*update) P((Handle **, Ref *, void *)))
  48. {
  49.     register Handle *h;
  50.     register HRef *rp;
  51.     register int i;
  52.  
  53.     if(hp == NULL || (h = *hp) == NULL)
  54.     return;
  55.  
  56.     for(i = h->nrefs, rp = &h->refs[i]; --i >= 0; ) {
  57.     rp--;
  58.     if(rp->hp == hp &&
  59.             (obj == NULL || rp->parentobj == obj) &&
  60.             (info == NULL || rp->info == info) &&
  61.             (update == NULL || rp->update == update)) {
  62.         *rp = h->refs[--h->nrefs];
  63.     }
  64.     }
  65. }
  66.  
  67. /*
  68.  * Remove all callbacks on any handle with the given properties.
  69.  */
  70. void HandleUnregisterAll(Ref *obj, void *info, void (*update) P((Handle **, Ref *, void *)))
  71. {
  72.     register Handle *h;
  73.     register HRef *rp;
  74.     register int i;
  75.  
  76.     for(h = AllHandles; h != NULL; h = h->next) {
  77.     for(i = h->nrefs, rp = &h->refs[i]; --i >= 0; ) {
  78.         rp--;
  79.         if((obj == NULL || rp->parentobj == obj) &&
  80.             (info == NULL || rp->info == info) &&
  81.             (update == NULL || rp->update == update)) {
  82.         *rp = h->refs[--h->nrefs];
  83.         }
  84.     }
  85.     }
  86. }
  87.  
  88. static
  89. void handleupdate(Handle *h, register HRef *rp)
  90. {
  91.     if(rp->update && h == *rp->hp)
  92.     (*rp->update)(rp->hp, rp->parentobj, rp->info);
  93.     else { /* BUG */
  94.     OOGLError(1, "handleupdate mismatch: h %x %s, rp->hp %x, *rp->hp %x, rp->parentobj %x, rp->update %x",
  95.         h, h->name, rp->hp, *rp->hp, rp->parentobj, rp->update);
  96.     if(*rp->hp)
  97.         OOGLError(1, "... *rp->hp->name %s", (*rp->hp)->name);
  98.     }
  99. }
  100.  
  101. int HandleRegister(Handle **hp, Ref *parentobj, void *info, void (*update) P((Handle **, Ref *, void *)))
  102. {
  103.     register Handle *h;
  104.     register HRef *rp;
  105.     register int i;
  106.  
  107.     if(hp == NULL || (h = *hp) == NULL)
  108.     return 0;
  109.     for(i = h->nrefs, rp = h->refs; --i > 0; rp++) {
  110.     if(rp->hp == hp && rp->parentobj == parentobj && rp->info == info)
  111.         goto doit;
  112.     }
  113.  
  114.     if(h->nrefs >= h->maxrefs) {
  115.     h->refs = h->maxrefs == 0 ?
  116.         OOGLNewNE(HRef, (h->maxrefs = 3), "HandleRegister") :
  117.         OOGLRenewNE(HRef, h->refs, (h->maxrefs += h->maxrefs+1),
  118.                 "HandleRegister");
  119.     }
  120.     rp = &h->refs[h->nrefs++];
  121.  
  122.     rp->hp = hp;
  123.   doit:
  124.     rp->parentobj = parentobj;
  125.     rp->info = info;
  126.     rp->update = update;
  127.     /* handleupdate(h, rp);    Do we need this?  I hope not. - slevy */
  128.     return 1;
  129. }
  130.  
  131. char *
  132. HandleName(Handle *h)
  133. {
  134.    return h ? h->name : NULL;
  135. }
  136.  
  137. Handle *
  138. HandleByName(char *name, HandleOps *ops)
  139. {
  140.     register Handle *h;
  141.  
  142.     for(h = AllHandles; h != NULL; h = h->next) {
  143.     if(h->ops == ops && strcmp(h->name, name) == 0)
  144.         return h;
  145.     }
  146.     return NULL;
  147. }
  148.  
  149. static Handle *
  150. handlecreate(char *name, HandleOps *ops)
  151. {
  152.     register Handle *h;
  153.  
  154.     h = OOGLNewE(Handle, "new Handle");
  155.     RefInit((Ref *)h, HANDLEMAGIC);
  156.     h->ops = ops;
  157.     h->name = strdup(name);
  158.     h->object = NULL;
  159.     h->maxrefs = 0;
  160.     h->nrefs = 0;
  161.     h->refs = NULL;
  162.     h->whence = NULL;
  163.     h->permanent = 1;
  164.     h->next = AllHandles;
  165.     AllHandles = h;
  166.     return h;
  167. }
  168.  
  169. /*
  170.  * Assign a new object to a Handle.
  171.  */
  172. int
  173. HandleSetObject(register Handle *h, Ref *object)
  174. {
  175.     register int i;
  176.     Ref *oldobj;
  177.  
  178.     if(h == NULL)
  179.     return 0;
  180.  
  181.     if(h->object == object)
  182.     return 1;
  183.  
  184.     oldobj = h->object;
  185.     h->object = object;
  186.     if(h->ops->Delete != NULL) {
  187.     if(oldobj) (*h->ops->Delete)(oldobj);
  188.     RefIncr(object);
  189.     }
  190.  
  191.     if(object != NULL && object->handle == NULL)
  192.     object->handle = h;
  193.  
  194.     for(i = h->nrefs; --i >= 0; )
  195.     handleupdate(h, &h->refs[i]);
  196.  
  197.     return 1;
  198. }
  199.  
  200. /*
  201.  * Create a Handle, don't reassign its value.
  202.  */
  203. Handle *
  204. HandleCreate(char *name, HandleOps *ops)
  205. {
  206.     register Handle *h;
  207.  
  208.     h = HandleByName(name, ops);
  209.     if(h == NULL) h = handlecreate(name, ops);
  210.     return h;
  211. }
  212.  
  213. /*
  214.  * Create a Handle (or reassign its value if it already exists)
  215.  */
  216. Handle *
  217. HandleAssign(char *name, HandleOps *ops, Ref *object)
  218. {
  219.     register Handle *h;
  220.  
  221.     h = HandleByName(name, ops);
  222.     if(h == NULL)
  223.     h = handlecreate(name, ops);
  224.     HandleSetObject(h, object);
  225.     return h;
  226. }
  227.  
  228. /*
  229.  * Return the current object held by a Handle.
  230.  */
  231. Ref *
  232. HandleObject(Handle *h)
  233. { return h->object; }
  234.  
  235. void HandlePDelete(Handle **hp)
  236. {
  237.     if(hp && *hp) {
  238.     HandleUnregister(hp);
  239.     HandleDelete(*hp);
  240.     }
  241. }
  242.  
  243. void HandleDelete(Handle *h)
  244. {
  245.   register Handle **hp;
  246.  
  247.   if(h == NULL)
  248.     return;
  249.   /*
  250.    * Don't delete a Handle if it still has active references.
  251.    * Also don't delete Handles marked "permanent"; those loaded with '<'
  252.    * aren't permanent, but others are.
  253.    */
  254.   if(h->nrefs > 0 || h->permanent) {
  255.     if(h->ref_count > 0) RefDecr((Ref *)h);
  256.     return;
  257.   }
  258. #ifdef HANDLE_REF_COUNTS_OK
  259.   if(RefDecr((Ref*)h) > 0)
  260.     return;
  261. #else
  262.   /* Avoid RefDecr() error messages.
  263.    * We're not correctly maintaining Handle ref counts in the rest of the code.
  264.    * Until we do, avoid spurious RefDecr() error messages.
  265.    * Note that we never actually free a Handle under this ifdef case,
  266.    * so there's no danger of reusing freed memory.  -SL 92.08.31
  267.    */
  268.   if(h->ref_count == 0 || RefDecr((Ref *)h) > 0)
  269.     return;
  270. #endif
  271.  
  272.   if(h->object && h->object->handle == h && h->ops->Delete && h->object->ref_count > 0) {
  273.     h->object->handle = NULL;
  274.     (*h->ops->Delete)(h->object);
  275.   }
  276.   for(hp = &AllHandles; *hp != NULL; hp = &(*hp)->next) {
  277.     if(*hp == h) {
  278.     *hp = h->next;
  279.     break;
  280.     }
  281.   }
  282.  
  283.   /* Don't let Pool code think we have something cached in this handle! */
  284.   if(h->whence && h->whence->seekable) {
  285.     h->whence->flags &= ~PF_ANY;
  286.     PoolClose(h->whence);
  287.     h->whence = 0;
  288.   }
  289. #ifdef HANDLE_REF_COUNTS_OK
  290.   h->object = NULL;
  291.   if(h->refs)
  292.     OOGLFree(h->refs);
  293.   if(h->name)
  294.     free(h->name);
  295.   OOGLFree(h);
  296. #else
  297.   /* Suspect that some Handles are being used after deletion.
  298.    * Invalidate the object pointer to cause a likely crash,
  299.    * but leave the Handle in memory as a debugging aid.  -slevy 92.07.27
  300.    */
  301.   h->object = (Ref *)((long)h->object | 1);
  302. #endif
  303. }
  304.